package com.clouddms.service.security;

import com.clouddms.service.common.IService;
import com.clouddms.service.common.ServiceStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 密钥管理服务
 * 负责密钥的生成、存储、轮换和管理
 *
 * @author Cloud-DMS Team
 * @version 1.0.0
 */
@Slf4j
@Service
public class KeyManagerService implements IService {

    @Value("${clouddms.security.encryption.key:CloudDMSAESKey2024}")
    private String masterKey;

    @Value("${clouddms.security.encryption.algorithm:AES}")
    private String algorithm;

    // 密钥缓存 - 生产环境应该使用更安全的存储方式
    private final Map<String, SecretKey> keyCache = new ConcurrentHashMap<>();
    private final Map<String, Long> keyCreationTime = new ConcurrentHashMap<>();
    private final SecureRandom secureRandom = new SecureRandom();

    // 密钥有效期 (24小时)
    private static final long KEY_VALIDITY_PERIOD = 24 * 60 * 60 * 1000L;
    private static final int AES_KEY_LENGTH = 256;

    // === IService 接口实现 ===

    @Override
    public String getServiceName() {
        return "keyManager";
    }

    @Override
    public String getDisplayName() {
        return "密钥管理服务";
    }

    @Override
    public String getDescription() {
        return "负责AES密钥的生成、管理、轮换，提供安全的密钥存储和访问控制";
    }

    @Override
    public ServiceStatus getStatus() {
        return ServiceStatus.RUNNING;
    }

    @Override
    public int getPriority() {
        return 25; // 高优先级，安全基础服务
    }

    // === 密钥管理业务方法 ===

    /**
     * 获取用户的文件加密密钥
     *
     * @param userId 用户ID
     * @return 加密密钥
     */
    public SecretKey getUserFileKey(Long userId) {
        String keyId = "user_file_" + userId;
        
        SecretKey key = keyCache.get(keyId);
        Long creationTime = keyCreationTime.get(keyId);
        
        // 检查密钥是否存在且未过期
        if (key == null || creationTime == null || isKeyExpired(creationTime)) {
            log.info("为用户 {} 生成新的文件加密密钥", userId);
            key = generateUserFileKey(userId);
            keyCache.put(keyId, key);
            keyCreationTime.put(keyId, System.currentTimeMillis());
        }
        
        return key;
    }

    /**
     * 获取系统级密钥
     *
     * @param keyType 密钥类型
     * @return 系统密钥
     */
    public SecretKey getSystemKey(String keyType) {
        String keyId = "system_" + keyType;
        
        SecretKey key = keyCache.get(keyId);
        if (key == null) {
            log.info("生成系统密钥: {}", keyType);
            key = generateSystemKey(keyType);
            keyCache.put(keyId, key);
            keyCreationTime.put(keyId, System.currentTimeMillis());
        }
        
        return key;
    }

    /**
     * 生成随机的AES密钥
     *
     * @return AES密钥
     */
    public SecretKey generateRandomAESKey() {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(algorithm);
            keyGenerator.init(AES_KEY_LENGTH);
            SecretKey secretKey = keyGenerator.generateKey();
            
            log.debug("生成随机AES密钥: {} 位", AES_KEY_LENGTH);
            return secretKey;
            
        } catch (NoSuchAlgorithmException e) {
            log.error("生成AES密钥失败: {}", e.getMessage(), e);
            throw new RuntimeException("无法生成AES密钥", e);
        }
    }

    /**
     * 密钥轮换 - 为指定用户生成新密钥
     *
     * @param userId 用户ID
     * @return 新密钥
     */
    public SecretKey rotateUserKey(Long userId) {
        String keyId = "user_file_" + userId;
        
        log.info("执行用户 {} 的密钥轮换", userId);
        
        // 移除旧密钥
        keyCache.remove(keyId);
        keyCreationTime.remove(keyId);
        
        // 生成新密钥
        return getUserFileKey(userId);
    }

    /**
     * 清理过期密钥
     */
    public void cleanupExpiredKeys() {
        long currentTime = System.currentTimeMillis();
        int cleanedCount = 0;
        
        for (Map.Entry<String, Long> entry : keyCreationTime.entrySet()) {
            if (isKeyExpired(entry.getValue())) {
                String keyId = entry.getKey();
                keyCache.remove(keyId);
                keyCreationTime.remove(keyId);
                cleanedCount++;
                log.debug("清理过期密钥: {}", keyId);
            }
        }
        
        if (cleanedCount > 0) {
            log.info("清理了 {} 个过期密钥", cleanedCount);
        }
    }

    /**
     * 获取密钥信息统计
     *
     * @return 密钥统计信息
     */
    public KeyStatistics getKeyStatistics() {
        long currentTime = System.currentTimeMillis();
        int totalKeys = keyCache.size();
        int activeKeys = 0;
        int expiredKeys = 0;
        
        for (Long creationTime : keyCreationTime.values()) {
            if (isKeyExpired(creationTime)) {
                expiredKeys++;
            } else {
                activeKeys++;
            }
        }
        
        return new KeyStatistics(totalKeys, activeKeys, expiredKeys);
    }

    /**
     * 将密钥转换为Base64字符串（用于存储）
     *
     * @param key 密钥
     * @return Base64编码的密钥
     */
    public String encodeKey(SecretKey key) {
        return Base64.getEncoder().encodeToString(key.getEncoded());
    }

    /**
     * 从Base64字符串恢复密钥
     *
     * @param encodedKey Base64编码的密钥
     * @return 密钥对象
     */
    public SecretKey decodeKey(String encodedKey) {
        byte[] decodedKey = Base64.getDecoder().decode(encodedKey);
        return new SecretKeySpec(decodedKey, algorithm);
    }

    // === 私有方法 ===

    /**
     * 为用户生成文件加密密钥
     */
    private SecretKey generateUserFileKey(Long userId) {
        try {
            // 使用用户ID和主密钥派生用户专用密钥
            String keyMaterial = masterKey + "_user_" + userId + "_" + System.currentTimeMillis();
            byte[] keyBytes = keyMaterial.getBytes();
            
            // 使用PBKDF2或类似方法派生密钥（这里简化处理）
            byte[] derivedKey = deriveKey(keyBytes, ("salt_" + userId).getBytes());
            
            return new SecretKeySpec(derivedKey, algorithm);
            
        } catch (Exception e) {
            log.error("生成用户文件密钥失败: {}", e.getMessage(), e);
            throw new RuntimeException("无法生成用户密钥", e);
        }
    }

    /**
     * 生成系统级密钥
     */
    private SecretKey generateSystemKey(String keyType) {
        try {
            String keyMaterial = masterKey + "_system_" + keyType;
            byte[] keyBytes = keyMaterial.getBytes();
            byte[] derivedKey = deriveKey(keyBytes, ("system_salt_" + keyType).getBytes());
            
            return new SecretKeySpec(derivedKey, algorithm);
            
        } catch (Exception e) {
            log.error("生成系统密钥失败: {}", e.getMessage(), e);
            throw new RuntimeException("无法生成系统密钥", e);
        }
    }

    /**
     * 简单的密钥派生函数（生产环境应使用PBKDF2）
     */
    private byte[] deriveKey(byte[] password, byte[] salt) {
        byte[] derived = new byte[32]; // 256位密钥
        
        for (int i = 0; i < derived.length; i++) {
            derived[i] = (byte) (password[i % password.length] ^ salt[i % salt.length] ^ (i & 0xFF));
        }
        
        return derived;
    }

    /**
     * 检查密钥是否过期
     */
    private boolean isKeyExpired(Long creationTime) {
        return System.currentTimeMillis() - creationTime > KEY_VALIDITY_PERIOD;
    }

    /**
     * 密钥统计信息
     */
    public static class KeyStatistics {
        private final int totalKeys;
        private final int activeKeys;
        private final int expiredKeys;

        public KeyStatistics(int totalKeys, int activeKeys, int expiredKeys) {
            this.totalKeys = totalKeys;
            this.activeKeys = activeKeys;
            this.expiredKeys = expiredKeys;
        }

        // Getters
        public int getTotalKeys() { return totalKeys; }
        public int getActiveKeys() { return activeKeys; }
        public int getExpiredKeys() { return expiredKeys; }
        
        @Override
        public String toString() {
            return String.format("KeyStatistics{总计=%d, 活跃=%d, 过期=%d}", 
                totalKeys, activeKeys, expiredKeys);
        }
    }
}